package com.ly.juc;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalTime;
import java.util.concurrent.*;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.List;

/**
 * @Classname TestCompletableFuture
 * @Description TODO
 * @Date 2020/10/5 10:44
 * @Author 冷心影翼
 */
public class TestCompletableFuture {

	public static void main(String[] args) throws ExecutionException, InterruptedException {
		ExecutorService threadPoolExecutor = new ThreadPoolExecutor(
			Runtime.getRuntime().availableProcessors() / 2,
			Runtime.getRuntime().availableProcessors(),
			5,
			TimeUnit.SECONDS,
			new LinkedBlockingQueue<>(),
			Executors.defaultThreadFactory(),
			new ThreadPoolExecutor.AbortPolicy()
		);
		UserDao userDao = new UserDao();
		Instant start = Instant.now();
		CompletableFuture<Void> insert1 = CompletableFuture.runAsync(()->{
			try {
				userDao.insertUser(new User(1,"A"));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		},threadPoolExecutor);

		CompletableFuture<Void> insert2 = CompletableFuture.runAsync(()->{
			try {
				userDao.insertUser(new User(2,"B"));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		},threadPoolExecutor);

		CompletableFuture<Void> endInsert = CompletableFuture.allOf(insert1,insert2);
		endInsert.get();
		CompletableFuture<List<User>> select = CompletableFuture.supplyAsync(()->{
			try {
				return userDao.getAll();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return null;
		},threadPoolExecutor);

		select.whenCompleteAsync((u,e)->{
			System.out.println("u:"+u);
			System.out.println("e:"+e);
			try {
				userDao.deleteUser(	u.get(0));
			} catch (InterruptedException e2) {
				e.printStackTrace();
			}
		},threadPoolExecutor).get();
		Instant end = Instant.now();
		System.out.println(userDao.users);
		System.out.println(Duration.between(start,end).getSeconds());
		threadPoolExecutor.shutdown();
	}

}


@Data
@AllArgsConstructor
class User {
	private int age;
	private String name;
}

class UserDao {
	 List<User> users = new CopyOnWriteArrayList<>();

	public void insertUser(User u) throws InterruptedException {
		users.add(u);
		TimeUnit.SECONDS.sleep(1);
	}

	public void deleteUser(User u) throws InterruptedException {
		users.remove(u);
		TimeUnit.SECONDS.sleep(2);
	}

	public List<User> getAll() throws InterruptedException {
		TimeUnit.MILLISECONDS.sleep(5000);
		return users;
	}
}